﻿Imports Microsoft.Practices.Mobile.Configuration
Imports Microsoft.Practices.Mobile.ConnectionMonitor
Imports Microsoft.Practices.Mobile.DisconnectedAgent
Imports Microsoft.Practices.Mobile.DataAccess
Imports Microsoft.Practices.Mobile.EndpointCatalog
Imports System.Data.SqlServerCe
Imports DSAGettingStarted.HelloWorldServiceProxy

Public Class MainForm

    Private WithEvents _connectionMonitor As ConnectionMonitor
    Private WithEvents _requestManager As RequestManager
    Private _database As Database
    Private _endpoints As IEndpointCatalog
    Private _connectionMonitorAdapter As IConnectionMonitor

    ' Define a delegate type for the form's DisplayConnectionStatus method.
    Private Delegate Sub DisplayConnectionStatusDelegateType()
    ' Declare a delegate variable to point
    ' to the form's DisplayConnectionStatus method.
    Private m_DisplayConnectionStatusDelegate As DisplayConnectionStatusDelegateType = AddressOf DisplayStatus


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' Initialize disconnected service agent
        _connectionMonitor = ConnectionMonitorFactory.CreateFromConfiguration()

        ' Init database object
        Dim filename As String = System.IO.Path.Combine(DirectoryUtils.BaseDirectory, "AppDatabase.sdf")
        Dim connectionString As String = String.Format("Data Source=""{0}""", filename)
        If Not System.IO.File.Exists(filename) Then
            Dim eng As SqlCeEngine = New SqlCeEngine(connectionString)
            eng.CreateDatabase()
        End If
        _database = New SqlDatabase(connectionString)

        ' ...and an IEndpointsCatalog
        Dim factory As IEndpointCatalogFactory = New EndpointCatalogFactory("Endpoints")
        _endpoints = factory.CreateCatalog()

        ' Finally init the Agent, using the database, endpoint catalog and connection monitor
        _connectionMonitorAdapter = New ConnectionMonitorAdapter(_connectionMonitor)
        _requestManager = RequestManager.Instance
        _requestManager.Initialize(_endpoints, _connectionMonitorAdapter, _database)
        _requestManager.StartAutomaticDispatch()

        DisplayStatus()
    End Sub

    Private Sub QueueDSARequest(ByVal message As String, ByVal numberStamps As Integer)
        ' Create our own OffLineBehaviour
        Dim behavior As OfflineBehavior = New OfflineBehavior()
        behavior.MaxRetries = 3
        behavior.MessageId = Guid.NewGuid()  ' IMPORTANT for Idempotency 
        behavior.Stamps = numberStamps
        behavior.ReturnCallback = New CommandCallback(GetType(DSACallbacks), "OnSendSuccess")
        behavior.ExceptionCallback = New CommandCallback(GetType(DSACallbacks), "OnSendException")

        ' Set up the request
        Dim request As Request = New Request()
        request.MethodName = "HelloWorld"
        request.Behavior = behavior
        request.CallParameters = New Object() {message}
        ' Set the Web Service proxy type and endpoint name
        request.OnlineProxyType = GetType(HelloWorldService)
        request.Endpoint = "HelloWorldService"

        ' Enqueue the request
        RequestManager.Instance.RequestQueue.Enqueue(request)

        DisplayStatus()

    End Sub

    ''' <summary>
    ''' Hook the RequestDispatched event of the RequestManager, so we are notified of successful
    ''' despatch, but also of requests that have exceeded their retry count and have gone to the 
    ''' dead letter queue
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub _requestManager_RequestDispatched(ByVal sender As Object, ByVal e As Microsoft.Practices.Mobile.DisconnectedAgent.RequestDispatchedEventArgs) Handles _requestManager.RequestDispatched
        DisplayStatus()

        If e.Result = DispatchResultStatus.Failed Then
            MessageBox.Show("Request failed and sent to Dead Letter Queue")
            ' Action is app dependant. You may wish to requeue messages from the Dead Letter Queue
            ' but be careful of introducing race conditions where a request is continually resubmitted
            ' and continually fails.
        End If
    End Sub

    Private Sub Send10StampsMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Send10StampsMenuItem.Click

        ' Queue the order to the Disconnected Service Agent;
        QueueDSARequest("Message queued with 10 stamps at " & DateTime.Now.ToShortTimeString(), 10)

    End Sub

    Private Sub Send1StampMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Send1StampMenuItem.Click

        ' Queue the order to the Disconnected Service Agent;
        QueueDSARequest("Message queued with 1 stamp at " & DateTime.Now.ToShortTimeString(), 1)

    End Sub

    Private Sub DisplayStatus()
        If Me.InvokeRequired Then
            Me.Invoke(m_DisplayConnectionStatusDelegate)
        Else
            ' Executing on the GUI thread, so set the Label control
            If _connectionMonitor.IsConnected Then
                For Each conn As Connection In _connectionMonitor.ActiveConnections
                    lblConnectionStatus.Text = "Connected to " & conn.ConnectionTypeName & ", Price: " & conn.Price.ToString() & vbCrLf
                Next
            Else
                lblConnectionStatus.Text = "Not connected to a network"
            End If

            ' List requests in the request queue
            dgRequestBindingSource.DataSource = _requestManager.RequestQueue.GetRequests()
            dgRequests.DataSource = dgRequestBindingSource
            ' and in the Dead letter queue
            dgDeadLetterBindingSource.DataSource = _requestManager.DeadLetterQueue.GetRequests()
            dgDeadLetter.DataSource = dgDeadLetterBindingSource
        End If
    End Sub

    ''' <summary>
    ''' Event handler for the ConnectionStatusChanged event of the ConnectionMonitor
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub _connectionMonitor_ConnectionStatusChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _connectionMonitor.ConnectionStatusChanged
        DisplayStatus()
    End Sub
End Class

Public Class DSACallbacks
    Public Sub OnSendSuccess(ByVal req As Request, ByVal qParams() As Object, ByVal returnValue As String)
        ' Do something  with response from Web service
        MessageBox.Show("Callback from Disconnected Service Agent: " & returnValue)

    End Sub

    Public Function OnSendException(ByVal req As Request, ByVal ex As Exception) As OnExceptionAction
        ' Exception in sending Web request
        MessageBox.Show("Exception Callback from Disconnected Service Agent: " + ex.Message)
        ' Send back OnExceptionAction.Retry to retry the request immediately, max number of retries
        ' is specified in the OfflineBehavior.MaxRetries property when submitting the request.
        ' Send back OnExceptionAction.Dismiss to tell the RequestManager to give up on this one and to 
        ' send it to the dead letter queue
        Return OnExceptionAction.Retry
    End Function
End Class
